package com.wstuo.common.acl.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.DefaultPermissionFactory;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.acls.model.Sid;
import org.springframework.transaction.annotation.Transactional;

import com.wstuo.common.acl.dao.IAclsDAO;
import com.wstuo.common.acl.dto.AclDTO;
import com.wstuo.common.acl.dto.EntriesDTO;
import com.wstuo.common.acl.entity.ACL_Entry;
import com.wstuo.common.security.dao.IOrganizationDAO;
import com.wstuo.common.security.dao.IRoleDAO;
import com.wstuo.common.security.dto.OrganizationDTO;
import com.wstuo.common.security.dto.UserDTO;
import com.wstuo.common.security.dto.UserDetailDTO;
import com.wstuo.common.security.entity.Organization;
import com.wstuo.common.security.entity.Role;
import com.wstuo.common.security.service.IUserInfoService;
import com.wstuo.common.util.StringUtils;

/**
 * ACL Service Class
 * @author Administrator
 *
 */
public class AclsService implements IAclsService {

	@Autowired
	private IUserInfoService userInfoService;
	@Autowired
	private IAclsDAO aclsDAO;
	@Autowired
	private MutableAclService mutableAclService;
	private DefaultPermissionFactory defaultPermissionFactory = new DefaultPermissionFactory();
	@Autowired
	private IRoleDAO roleDAO;
	@Autowired
	private IOrganizationDAO organizationDAO;
	
	/**
	 * 创建ACL权限
	 * @param aclClass 类名
	 * @param identifier 标识码
	 */
	@Transactional
	public void createAcl(String aclClass, Long identifier) {
		// TODO Auto-generated method stub
		ObjectIdentity oid = new ObjectIdentityImpl(aclClass,identifier);
        MutableAcl acl = mutableAclService.createAcl(oid);
        //取当前登录账号：
        UserDTO  userDTO = userInfoService.getCurrentLoginUser();
        if(userDTO!=null && userDTO.getLoginName()!=null){
        	//管理员权限分给操作用户
            acl.insertAce(0, BasePermission.ADMINISTRATION,
            	    new PrincipalSid(userDTO.getLoginName()), true);	
        }
        //默认把权限“ADMINISTRATION”赋给“SYSADMIN”管理员角色
/*        acl.insertAce(1, BasePermission.ADMINISTRATION,
            new GrantedAuthoritySid("ROLE_SYSADMIN"), true);*/
        	
        mutableAclService.updateAcl(acl);
	}
	/**
	 * 创建ACL权限,默认赋予管理员限
	 * @param aclClass
	 * @param identifier
	 */
	@Transactional
	public void createAclEveryone(String aclClass, Long identifier){
		ObjectIdentity oid = new ObjectIdentityImpl(aclClass,identifier);
        MutableAcl acl = mutableAclService.createAcl(oid);
        //管理员权限分给操作用户
        acl.insertAce(0, BasePermission.ADMINISTRATION,
        	    new PrincipalSid("Everyone"), true);	
        	
        mutableAclService.updateAcl(acl);
	}
	
	/**
	 * 删除ACL权限
	 * @param aclClass 类名
	 * @param identifier 标识码
	 */
	@Transactional
	public void deleteAcl(String aclClass, Long identifier){
		ObjectIdentity oid = new ObjectIdentityImpl(aclClass,identifier);
        mutableAclService.deleteAcl(oid, false);
	}
	
	/**
	 * 查询当前账号查询拥有相应(读）权限的资源
	 * @param loginName 类名
	 * @param aclClass 标识码
	 * @param permissions 权限标识
	 * @return all acl resource
	 */
	@Transactional
	public Set<Long> findAclResourceId(String loginName, String aclClass,Integer[] permissions) {
		// TODO Auto-generated method stub
		Set<Long> resId = new HashSet<Long>();
		resId.add(0L);
		UserDetailDTO userDetailDTO = userInfoService.findUserByUserIdAndLogName(null, loginName);
		Set<String> sids = new HashSet<String>();
		sids.add(loginName);
		sids.add("Everyone");
		//角色
		if(userDetailDTO!=null && userDetailDTO.getRoleCode()!=null){
			for(String roleCode : userDetailDTO.getRoleCode()){
				sids.add(roleCode);
			}
		}
		//所属组
		if(userDetailDTO!=null && userDetailDTO.getBelongsGroups()!=null){
			for(OrganizationDTO org : userDetailDTO.getBelongsGroups()){
				sids.add("GROUP_"+org.getOrgNo());
			}
		}
		
		List<ACL_Entry> aclEntrys = aclsDAO.findAcl(sids, aclClass, permissions, null);
		for(ACL_Entry ae : aclEntrys){
			Long object_id_identity = (Long)ae.getAcl_object_identity().getObject_id_identity();
			resId.add(object_id_identity);
		}
		return resId;
	}
	
	/**
	 * 查询ACL
	 * @param aclClass 类名
	 * @param identifier 标识码
	 * @return acl
	 */
	@Transactional
	public Acl findAclByClassObjectId(String aclClass, Long identifier) {
		// TODO Auto-generated method stub
		Acl acl = null;
		ObjectIdentity oid = new ObjectIdentityImpl(aclClass, identifier);
		try{
			acl = mutableAclService.readAclById(oid);
		}catch(Exception ex){
			createAcl(aclClass,identifier);
			acl = mutableAclService.readAclById(oid);
		}
		
		return acl;
	}
	
	/**
	 * 查询当前
	 * @param loginName
	 * @param aclClass
	 * @param identitys
	 * @return acl permissiion
	 */
	@Transactional
	public Map<String,String> findAclPermission(String loginName, String aclClass,
			Long[] identitys) {
		// TODO Auto-generated method stub
		Map<String,String> permissions = new HashMap<String, String>();
		UserDetailDTO userDetailDTO = userInfoService.findUserByUserIdAndLogName(null, loginName);
		Set<String> sids = new HashSet<String>();
		sids.add(loginName);
		if(userDetailDTO!=null && userDetailDTO.getRoleCode()!=null){
			for(String roleCode : userDetailDTO.getRoleCode()){
				sids.add(roleCode);
			}
		}
		List<ACL_Entry> aclEntrys = aclsDAO.findAcl(sids, aclClass, null, identitys);
		for(ACL_Entry ae : aclEntrys){
			Long object_id_identity = (Long)ae.getAcl_object_identity().getObject_id_identity();
			String permission = permissions.get("objectId_"+object_id_identity);
			if(StringUtils.hasText(permission)){
				permissions.put("objectId_"+object_id_identity, permission+","+ae.getMask());
			}else{
				permissions.put("objectId_"+object_id_identity, ae.getMask()+"");
			}
		}
		return permissions;
	}
	
	
	
	/**
	 * 添加授权
	 * @param ids
	 * @param clz
	 * @param recipients
	 * @param masks
	 */
	@Transactional
	public void addPermission(Long[] ids, String clz, String[] recipients, int[] masks) {
		for(Long id : ids){//对多个资源进行授权
			for(String recipient : recipients){//给多个人或角色进行授权
				if(masks!=null){
					for(int mask : masks){//给个人或角色授权多个权限
						ObjectIdentity oid = new ObjectIdentityImpl(clz, id);
			    		MutableAcl acl;
						try {
						    acl = (MutableAcl) mutableAclService.readAclById(oid);
						} catch (NotFoundException nfe) {
						    acl = mutableAclService.createAcl(oid);
						}
						Permission permission = defaultPermissionFactory.buildFromMask(mask);
						Sid sid;
						if(recipient.indexOf("ROLE_")!=-1 || recipient.indexOf("GROUP_")!=-1){
							sid = new GrantedAuthoritySid(recipient);
						}else{
							sid = new PrincipalSid(recipient);
						}
						acl.insertAce(acl.getEntries().size(), permission, sid, true);
			 		    mutableAclService.updateAcl(acl);
			 	    }
				}
		    }
		}
	}
	
	/**
	 * 删除授权
	 * @param ids
	 * @param clz
	 * @param recipients
	 * @param masks
	 */
	@Transactional
	public void deletePermission(Long[] ids, String clz, String[] recipients,int[] masks) {
		for(long id : ids){
			for(String recipient : recipients){
				if(masks!=null && masks.length>0){
					
					Set<Integer> tempMask = new HashSet<Integer>();
					for(int mask : masks){
						tempMask.add(mask);
					}
					//tempMask.add(16);
					
					//删除中如果没有16也就是完全控制，在此收回授权中将16的权限删除
					for(int mask : masks){
						ObjectIdentity oid = new ObjectIdentityImpl(clz, id);
						Sid sid;
						if(recipient.indexOf("ROLE_")!=-1 || recipient.indexOf("GROUP_")!=-1){
							sid = new GrantedAuthoritySid(recipient);
						}else{
							sid = new PrincipalSid(recipient);
						}
						Permission permission = defaultPermissionFactory.buildFromMask(mask);
						if(permission!=null){
							MutableAcl acl = (MutableAcl) mutableAclService.readAclById(oid);
							List<AccessControlEntry> entries = acl.getEntries();
							for (int i = 0; i < entries.size(); i++) {
						        if (entries.get(i).getSid().equals(sid)
						                && entries.get(i).getPermission().equals(permission)) {
						            acl.deleteAce(i);
						        }
						    }
							
						    mutableAclService.updateAcl(acl);
						}
						
					}
				}
			}
		}
	}
	
	/**
	 * 查询标识的权限
	 * @param identitys
	 * @param aclclass
	 * @return List<AclDTO>
	 */
	@Transactional
	public List<AclDTO> findAclByClzIds(Long[] identitys,String aclclass){
		List<AclDTO> aclDTOs = new ArrayList<AclDTO>();
		for(Long id : identitys){
			AclDTO aclDTO = new AclDTO(); 
			Acl acl = findAclByClassObjectId(aclclass,id);
			if(acl!=null){
				PrincipalSid sid = (PrincipalSid)acl.getOwner();
				aclDTO.setOwner_principal(sid.getPrincipal());
				UserDetailDTO userDetailDTO = userInfoService.findUserByUserIdAndLogName(null, sid.getPrincipal());
				aclDTO.setOwner_principalName(userDetailDTO.getLoginName());
				aclDTO.setObjectIdentity_identifier((Long)acl.getObjectIdentity().getIdentifier());
				aclDTO.setObjectIdentity_type(acl.getObjectIdentity().getType());
				//SID 拥有的权限
				Map<String, Set<Integer>> entries_permission_masks = new HashMap<String, Set<Integer>>();
				//SID对应的名称
				Map<String,String> entries_sid_names = new HashMap<String,String>();
				Set<String> entries_sids = new HashSet<String>();
				EntriesDTO entriesDTO = new EntriesDTO();
				for(AccessControlEntry ace : acl.getEntries()){
					String className = ace.getSid().getClass().getName();
					String entries_sid = "";
					String entries_sid_name = "";
					if("org.springframework.security.acls.domain.PrincipalSid".equals(className)){
						PrincipalSid principalSid = (PrincipalSid)ace.getSid();
						entries_sid = principalSid.getPrincipal();
						userDetailDTO = userInfoService.findUserByUserIdAndLogName(null, principalSid.getPrincipal());
						if(userDetailDTO!=null && userDetailDTO.getFullName()!=null)
							entries_sid_name = userDetailDTO.getFullName();
						else
							entries_sid_name = principalSid.getPrincipal();
					}
					if("org.springframework.security.acls.domain.GrantedAuthoritySid".equals(className)){
						GrantedAuthoritySid grantedAuthoritySid = (GrantedAuthoritySid)ace.getSid();
						entries_sid = grantedAuthoritySid.getGrantedAuthority();
						if(entries_sid.indexOf("ROLE_")!=-1){//角色
							Role role = roleDAO.findUniqueBy("roleCode", grantedAuthoritySid.getGrantedAuthority());
							entries_sid_name = role.getRoleName();
						}else if(entries_sid.indexOf("GROUP_")!=-1){//组
							Organization org  = organizationDAO.findById(Long.parseLong(entries_sid.substring(entries_sid.indexOf("_")+1)));
							entries_sid_name  = org.getOrgName();
						}
						
					}
					entries_sid_names.put(entries_sid, entries_sid_name);
					
					Set<Integer> masks = (Set<Integer>)entries_permission_masks.get(entries_sid);
					if(masks!=null){
						masks.add((Integer)ace.getPermission().getMask());
						entries_permission_masks.put(entries_sid,masks);
					}else{
						masks = new HashSet<Integer>();
						masks.add((Integer)ace.getPermission().getMask());
						entries_permission_masks.put(entries_sid,masks);
					}
					entries_sids.add(entries_sid);
				}
				entriesDTO.setEntries_sid(entries_sids);
				entriesDTO.setEntries_permission_mask(entries_permission_masks);
				entriesDTO.setEntries_sid_name(entries_sid_names);
				aclDTO.setEntries(entriesDTO);
			}
			aclDTOs.add(aclDTO);
		}
		return aclDTOs;
	}
	
	/**
	 * 更新授权
	 * @param ids
	 * @param clz
	 * @param recipients
	 * @param allowMasks
	 * @param rejectMasks
	 */
	@Transactional
	public void updatePermission(Long[] ids, String clz,
			String[] recipients, int[] allowMasks, int[] rejectMasks) {
		// TODO Auto-generated method stub
		addPermission(ids,clz,recipients,allowMasks);
		deletePermission(ids,clz,recipients,rejectMasks);
	}
	
	
}
